//===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config -------------===//
//
//                     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 LLVMCC configuration code.
//
//===----------------------------------------------------------------------===//

#include "LLVMCCConfigurationEmitter.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/Support/Streams.h"

#include <algorithm>
#include <cassert>
#include <functional>
#include <string>

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 = "            ";
const char * Indent4 = "                ";

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

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

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

std::string InitPtrToString(Init* ptr) {
  StringInit& val = dynamic_cast<StringInit&>(*ptr);
  return val.getValue();
}

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

// A command-line option can have one of the following types:
//
// Switch - a simple switch w/o arguments, e.g. -O2
//
// Parameter - an option that takes one(and only one) argument, e.g. -o file,
// --output=file
//
// ParameterList - same as Parameter, but more than one occurence
// of the option is allowed, e.g. -lm -lpthread
//
// Prefix - argument is everything after the prefix,
// e.g. -Wa,-foo,-bar, -DNAME=VALUE
//
// PrefixList - same as Prefix, but more than one option occurence is
// allowed

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

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

// Code duplication here is necessary because one option can affect
// several tools and those tools may have different actions associated
// with this option. GlobalOptionDescriptions are used to generate
// the option registration code, while ToolOptionDescriptions are used
// to generate tool-specific code.

// Base class for option descriptions

struct OptionDescription {
  OptionType::OptionType Type;
  std::string Name;

  OptionDescription(OptionType::OptionType t = OptionType::Switch,
                    const std::string& n = "")
  : Type(t), Name(n)
  {}

  const char* GenTypeDeclaration() const {
    switch (Type) {
    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 GenVariableName() const {
    switch (Type) {
    case OptionType::Switch:
     return "AutoGeneratedSwitch" + Name;
   case OptionType::Prefix:
     return "AutoGeneratedPrefix" + Name;
   case OptionType::PrefixList:
     return "AutoGeneratedPrefixList" + Name;
   case OptionType::Parameter:
     return "AutoGeneratedParameter" + Name;
   case OptionType::ParameterList:
   default:
     return "AutoGeneratedParameterList" + Name;
   }
  }

};

// Global option description

namespace GlobalOptionDescriptionFlags {
  enum GlobalOptionDescriptionFlags { Required = 0x1 };
}

struct GlobalOptionDescription : public OptionDescription {
  std::string Help;
  unsigned Flags;

  // StringMap can only store DefaultConstructible objects
  GlobalOptionDescription() : OptionDescription(), Flags(0)
  {}

  GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
    : OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
  {}

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

  // 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())
      Help = other.Help;
    else if (!Help.empty() && !other.Help.empty())
      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
struct GlobalOptionDescriptions {
  typedef StringMap<GlobalOptionDescription> container_type;
  typedef container_type::const_iterator const_iterator;

  // A list of GlobalOptionDescriptions
  container_type Descriptions;
  // Should the emitter generate a "cl::sink" option?
  bool HasSink;

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


// Tool-local option description

// Properties without arguments are implemented as flags
namespace ToolOptionDescriptionFlags {
  enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
                                    Forward = 0x2, UnpackValues = 0x4};
}
namespace OptionPropertyType {
  enum OptionPropertyType { AppendCmd };
}

typedef std::pair<OptionPropertyType::OptionPropertyType, std::string>
OptionProperty;
typedef SmallVector<OptionProperty, 4> OptionPropertyList;

struct ToolOptionDescription : public OptionDescription {
  unsigned Flags;
  OptionPropertyList Props;

  // StringMap can only store DefaultConstructible objects
  ToolOptionDescription() : OptionDescription(), Flags(0) {}

  ToolOptionDescription (OptionType::OptionType t, const std::string& n)
    : OptionDescription(t, n)
  {}

  // Various boolean properties
  bool isStopCompilation() const {
    return Flags & ToolOptionDescriptionFlags::StopCompilation;
  }
  void setStopCompilation() {
    Flags |= ToolOptionDescriptionFlags::StopCompilation;
  }

  bool isForward() const {
    return Flags & ToolOptionDescriptionFlags::Forward;
  }
  void setForward() {
    Flags |= ToolOptionDescriptionFlags::Forward;
  }

  bool isUnpackValues() const {
    return Flags & ToolOptionDescriptionFlags::UnpackValues;
  }
  void setUnpackValues() {
    Flags |= ToolOptionDescriptionFlags::UnpackValues;
  }

  void AddProperty (OptionPropertyType::OptionPropertyType t,
                    const std::string& val)
  {
    Props.push_back(std::make_pair(t, val));
  }
};

typedef StringMap<ToolOptionDescription> ToolOptionDescriptions;

// Tool information record

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

struct ToolProperties : public RefCountedBase<ToolProperties> {
  std::string Name;
  StrVector CmdLine;
  std::string InLanguage;
  std::string OutLanguage;
  std::string OutputSuffix;
  unsigned Flags;
  ToolOptionDescriptions OptDescs;

  // 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
  ToolProperties() {}
  ToolProperties (const std::string& n) : Name(n) {}
};


// A list of Tool information records
// IntrusiveRefCntPtrs are used 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
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*);

  // Map from property names -> 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 &);

  // Map from option property names -> option property handlers
  typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap;

  // Static maps from strings to CollectProperties methods("handlers")
  static PropertyHandlerMap propertyHandlers_;
  static OptionPropertyHandlerMap optionPropertyHandlers_;
  static bool staticMembersInitialized_;


  /// This is where the information is stored

  // Current Tool properties
  ToolProperties& toolProps_;
  // OptionDescriptions table(used to register options globally)
  GlobalOptionDescriptions& optDescs_;

public:

  explicit CollectProperties (ToolProperties& p, GlobalOptionDescriptions& d)
    : toolProps_(p), optDescs_(d)
  {
    if (!staticMembersInitialized_) {
      // Init tool property handlers
      propertyHandlers_["cmd_line"] = &CollectProperties::onCmdLine;
      propertyHandlers_["in_language"] = &CollectProperties::onInLanguage;
      propertyHandlers_["join"] = &CollectProperties::onJoin;
      propertyHandlers_["out_language"] = &CollectProperties::onOutLanguage;
      propertyHandlers_["output_suffix"] = &CollectProperties::onOutputSuffix;
      propertyHandlers_["parameter_option"]
        = &CollectProperties::onParameter;
      propertyHandlers_["parameter_list_option"] =
        &CollectProperties::onParameterList;
      propertyHandlers_["prefix_option"] = &CollectProperties::onPrefix;
      propertyHandlers_["prefix_list_option"] =
        &CollectProperties::onPrefixList;
      propertyHandlers_["sink"] = &CollectProperties::onSink;
      propertyHandlers_["switch_option"] = &CollectProperties::onSwitch;

      // Init option property handlers
      optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd;
      optionPropertyHandlers_["forward"] = &CollectProperties::onForward;
      optionPropertyHandlers_["help"] = &CollectProperties::onHelp;
      optionPropertyHandlers_["required"] = &CollectProperties::onRequired;
      optionPropertyHandlers_["stop_compilation"] =
        &CollectProperties::onStopCompilation;
      optionPropertyHandlers_["unpack_values"] =
        &CollectProperties::onUnpackValues;

      staticMembersInitialized_ = true;
    }
  }

  // Gets called for every tool property;
  // Just forwards to the corresponding property handler.
  void operator() (Init* i) {
    DagInit& d = dynamic_cast<DagInit&>(*i);
    std::string property_name = d.getOperator()->getAsString();
    PropertyHandlerMap::iterator method
      = propertyHandlers_.find(property_name);

    if (method != propertyHandlers_.end()) {
      PropertyHandler h = method->second;
      (this->*h)(&d);
    }
    else {
      throw "Unknown tool property: " + property_name + "!";
    }
  }

private:

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

  void onCmdLine (DagInit* d) {
    checkNumberOfArguments(d, 1);
    SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
    if (toolProps_.CmdLine.empty())
      throw std::string("Tool " + toolProps_.Name + " has empty command line!");
  }

  void onInLanguage (DagInit* d) {
    checkNumberOfArguments(d, 1);
    toolProps_.InLanguage = InitPtrToString(d->getArg(0));
  }

  void onJoin (DagInit* d) {
    checkNumberOfArguments(d, 0);
    toolProps_.setJoin();
  }

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

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

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

  /// 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) {
    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) {
    checkNumberOfArguments(d, 0);
    toolProps_.OptDescs[o.Name].setForward();
  }

  void onHelp (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) {
    checkNumberOfArguments(d, 0);
    o.setRequired();
  }

  void onStopCompilation (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) {
    checkNumberOfArguments(d, 0);
    toolProps_.OptDescs[o.Name].setUnpackValues();
  }

  /// Helper functions

  // Add an option of type t
  void addOption (DagInit* d, OptionType::OptionType t) {
    checkNumberOfArguments(d, 2);
    const std::string& name = InitPtrToString(d->getArg(0));

    GlobalOptionDescription o(t, name);
    toolProps_.OptDescs[name].Type = t;
    toolProps_.OptDescs[name].Name = name;
    processOptionProperties(d, o);
    insertDescription(o);
  }

  // Ensure that the number of args in d is <= min_arguments,
  // throw exception otherwise
  void checkNumberOfArguments (DagInit* d, unsigned min_arguments) {
    if (d->getNumArgs() < min_arguments)
      throw "Property " + d->getOperator()->getAsString()
        + " has too few arguments!";
  }

  // Insert new GlobalOptionDescription into GlobalOptionDescriptions list
  void insertDescription (const GlobalOptionDescription& o)
  {
    if (optDescs_.Descriptions.count(o.Name)) {
      GlobalOptionDescription& D = optDescs_.Descriptions[o.Name];
      D.Merge(o);
    }
    else {
      optDescs_.Descriptions[o.Name] = o;
    }
  }

  // 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) {
    // 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 std::string& option_property_name
        = option_property.getOperator()->getAsString();
      OptionPropertyHandlerMap::iterator method
        = optionPropertyHandlers_.find(option_property_name);

      if (method != optionPropertyHandlers_.end()) {
        OptionPropertyHandler h = method->second;
        (this->*h)(&option_property, o);
      }
      else {
        throw "Unknown option property: " + option_property_name + "!";
      }
    }
  }
};

// Static members of CollectProperties
CollectProperties::PropertyHandlerMap
CollectProperties::propertyHandlers_;

CollectProperties::OptionPropertyHandlerMap
CollectProperties::optionPropertyHandlers_;

bool CollectProperties::staticMembersInitialized_ = false;


// Gather information from the parsed TableGen data
// (Basically a wrapper for CollectProperties)
void CollectToolProperties (RecordVector::const_iterator B,
                            RecordVector::const_iterator E,
                            ToolPropertiesList& TPList,
                            GlobalOptionDescriptions& OptDescs)
{
  // Iterate over a properties list of every Tool definition
  for (;B!=E;++B) {
    RecordVector::value_type T = *B;
    ListInit* PropList = T->getValueAsListInit("properties");
    if (!PropList)
      throw std::string("Tool has no property list!");

    IntrusiveRefCntPtr<ToolProperties>
      ToolProps(new ToolProperties(T->getName()));

    std::for_each(PropList->begin(), PropList->end(),
                  CollectProperties(*ToolProps, OptDescs));
    TPList.push_back(ToolProps);
  }
}

// Used by EmitGenerateActionMethod
void EmitOptionPropertyHandlingCode (const ToolProperties& P,
                                     const ToolOptionDescription& D,
                                     std::ostream& O)
{
  // if clause
  O << Indent2 << "if (";
  if (D.Type == OptionType::Switch)
    O << D.GenVariableName();
  else
    O << '!' << D.GenVariableName() << ".empty()";

  O <<") {\n";

  // 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;

    switch (val.first) {
      // (append_cmd cmd) property
    case OptionPropertyType::AppendCmd:
      O << Indent3 << "vec.push_back(\"" << val.second << "\");\n";
      break;
      // Other properties with argument
    default:
      break;
    }
  }

  // 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;
    }
  }

  // (unpack_values) property
  if (D.isUnpackValues()) {
    if (IsListOptionType(D.Type)) {
      O << Indent3 << "for (" << D.GenTypeDeclaration()
        << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
        << Indent3 << "E = " << D.GenVariableName()
        << ".end(); B != E; ++B)\n"
        << Indent4 << "UnpackValues(*B, vec);\n";
    }
    else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){
      O << Indent3 << "UnpackValues("
        << D.GenVariableName() << ", vec);\n";
    }
    else {
      // TOFIX: move this to the type-checking phase
      throw std::string("Switches can't have unpack_values property!");
    }
  }

  // close if clause
  O << Indent2 << "}\n";
}

// Emite one of two versions of GenerateAction method
void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
{
  assert(V==1 || V==2);
  if (V==1)
    O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
  else
    O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";

  O << Indent2 << "const sys::Path& outFile) const\n"
    << Indent1 << "{\n"
    << Indent2 << "std::vector<std::string> vec;\n";

  // Parse CmdLine tool property
  StrVector::const_iterator I = P.CmdLine.begin();
  ++I;
  for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) {
    const std::string& cmd = *I;
    O << Indent2;
    if (cmd == "$INFILE") {
      if (V==1)
        O << "for (PathVector::const_iterator B = inFiles.begin()"
          << ", E = inFiles.end();\n"
          << Indent2 << "B != E; ++B)\n"
          << Indent3 << "vec.push_back(B->toString());\n";
      else
        O << "vec.push_back(inFile.toString());\n";
    }
    else if (cmd == "$OUTFILE") {
      O << "vec.push_back(outFile.toString());\n";
    }
    else {
      O << "vec.push_back(\"" << cmd << "\");\n";
    }
  }

  // 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
  if (P.isSink()) {
    O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
      << Indent3 << "vec.insert(vec.end(), "
      << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
      << Indent2 << "}\n";
  }

  O << Indent2 << "return Action(\"" << P.CmdLine.at(0) << "\", vec);\n"
    << Indent1 << "}\n\n";
}

// Emit GenerateAction methods for Tool classes
void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {

  if (!P.isJoin())
    O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
      << Indent2 << "const llvm::sys::Path& outFile) const\n"
      << Indent1 << "{\n"
      << Indent2 << "throw std::runtime_error(\"" << P.Name
      << " is not a Join tool!\");\n"
      << Indent1 << "}\n\n";
  else
    EmitGenerateActionMethod(P, 1, O);

  EmitGenerateActionMethod(P, 2, O);
}

// Emit IsLast() method for Tool classes
void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
  O << Indent1 << "bool IsLast() const {\n"
    << Indent2 << "bool last = false;\n";

  for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
        E = P.OptDescs.end(); B != E; ++B) {
    const ToolOptionDescription& val = B->second;

    if (val.isStopCompilation())
      O << Indent2
        << "if (" << val.GenVariableName()
        << ")\n" << Indent3 << "last = true;\n";
  }

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

// Emit static [Input,Output]Language() methods for Tool classes
void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
  O << Indent1 << "std::string InputLanguage() const {\n"
    << Indent2 << "return \"" << P.InLanguage << "\";\n"
    << Indent1 << "}\n\n";

  O << Indent1 << "std::string OutputLanguage() const {\n"
    << Indent2 << "return \"" << P.OutLanguage << "\";\n"
    << Indent1 << "}\n\n";
}

// Emit static [Input,Output]Language() methods for Tool classes
void EmitOutputSuffixMethod (const ToolProperties& P, std::ostream& O) {
  O << Indent1 << "std::string OutputSuffix() const {\n"
    << Indent2 << "return \"" << P.OutputSuffix << "\";\n"
    << Indent1 << "}\n\n";
}

// Emit static Name() method for Tool classes
void EmitNameMethod (const ToolProperties& P, std::ostream& O) {
  O << Indent1 << "std::string Name() const {\n"
    << Indent2 << "return \"" << P.Name << "\";\n"
    << Indent1 << "}\n\n";
}

// Emit static Name() method for Tool classes
void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
  O << Indent1 << "bool IsJoin() const {\n";
  if (P.isJoin())
    O << Indent2 << "return true;\n";
  else
    O << Indent2 << "return false;\n";
  O << Indent1 << "}\n\n";
}

// Emit a Tool class definition
void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
  // Header
  O << "class " << P.Name << " : public Tool {\n"
    << "public:\n";

  EmitNameMethod(P, O);
  EmitInOutLanguageMethods(P, O);
  EmitOutputSuffixMethod(P, O);
  EmitIsJoinMethod(P, O);
  EmitGenerateActionMethods(P, O);
  EmitIsLastMethod(P, O);

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

// Iterate over a list of option descriptions and emit registration code
void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
                             std::ostream& O)
{
  // Emit static cl::Option variables
  for (GlobalOptionDescriptions::const_iterator B = descs.begin(),
         E = descs.end(); B!=E; ++B) {
    const GlobalOptionDescription& val = B->second;

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

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

    if (val.isRequired()) {
      switch (val.Type) {
      case OptionType::PrefixList:
      case OptionType::ParameterList:
        O << ", cl::OneOrMore";
        break;
      default:
        O << ", cl::Required";
      }
    }

    O << ", cl::desc(\"" << val.Help << "\"));\n";
  }

  if (descs.HasSink)
    O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";

  O << '\n';
}

void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
{
  // Get the relevant field out of RecordKeeper
  Record* LangMapRecord = Records.getDef("LanguageMap");
  if (!LangMapRecord)
    throw std::string("Language map definition not found!");

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

  // Generate code
  O << "void llvmcc::PopulateLanguageMap(LanguageMap& language_map) {\n";

  for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
    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 << "language_map[\""
        << InitPtrToString(Suffixes->getElement(i))
        << "\"] = \"" << Lang << "\";\n";
  }

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

void EmitPopulateCompilationGraph (const RecordKeeper& Records,
                                   StringMap<std::string>& ToolToLang,
                                   std::ostream& O)
{
  // Get the relevant field out of RecordKeeper
  Record* ToolChains = Records.getDef("ToolChains");
  if (!ToolChains)
    throw std::string("No ToolChains specification found!");
  ListInit* chains = ToolChains->getValueAsListInit("chains");
  if (!chains)
    throw std::string("Error in toolchain list definition!");

  // Generate code
  O << "void llvmcc::PopulateCompilationGraph(CompilationGraph& G) {\n"
    << Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n"
    << Indent1 << "std::vector<IntrusiveRefCntPtr<Tool> > vec;\n\n";

  for (unsigned i = 0; i < chains->size(); ++i) {
    Record* ToolChain = chains->getElementAsRecord(i);
    ListInit* Tools = ToolChain->getValueAsListInit("tools");

    // Get name of the first tool in the list
    const std::string& firstTool =
      dynamic_cast<DefInit&>(**Tools->begin()).getDef()->getName();

    for (ListInit::iterator B = Tools->begin(),
          E = Tools->end(); B != E; ++B) {
      Record* val = dynamic_cast<DefInit&>(**B).getDef();
      O << Indent1 << "vec.push_back(IntrusiveRefCntPtr<Tool>(new "
        << val->getName() << "()));\n";
    }
    O << Indent1 << "G.ToolChains[\"" << ToolToLang[firstTool]
      << "\"] = vec;\n";
    O << Indent1 << "vec.clear();\n\n";
  }

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

void FillInToolToLang (const ToolPropertiesList& T,
                       StringMap<std::string>& M) {
  for (ToolPropertiesList::const_iterator B = T.begin(), E = T.end();
       B != E; ++B) {
    const ToolProperties& P = *(*B);
    M[P.Name] = P.InLanguage;
  }
}

// End of anonymous namespace
}

// Back-end entry point
void LLVMCCConfigurationEmitter::run (std::ostream &O) {
  // Emit file header
  EmitSourceFileHeader("LLVMCC Configuration Library", O);

  // 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
  ToolPropertiesList tool_props;
  GlobalOptionDescriptions opt_descs;
  CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs);

  // Emit global option registration code
  EmitOptionDescriptions(opt_descs, O);

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

  // Emit Tool classes
  for (ToolPropertiesList::const_iterator B = tool_props.begin(),
         E = tool_props.end(); B!=E; ++B)
    EmitToolClassDefinition(*(*B), O);

  // Fill in table that maps tool names to languages
  StringMap<std::string> ToolToLang;
  FillInToolToLang(tool_props, ToolToLang);

  // Emit PopulateCompilationGraph function
  EmitPopulateCompilationGraph(Records, ToolToLang, O);

  // EOF
}
