[llvm-commits] [llvm] r48699 - in /llvm/trunk: include/llvm/ADT/ tools/ tools/llvmc2/ tools/llvmc2/doc/ utils/TableGen/

Anton Korobeynikov asl at math.spbu.ru
Sun Mar 23 01:57:22 PDT 2008


Author: asl
Date: Sun Mar 23 03:57:20 2008
New Revision: 48699

URL: http://llvm.org/viewvc/llvm-project?rev=48699&view=rev
Log:
Add first proof-of-concept universal compiler driver framework based
on ideas mentioned in PR686.
Written by Mikhail Glushenkov and contributed by Codedgers, Inc.

Old llvmc will be removed soon after new one will have all its properties.

Added:
    llvm/trunk/tools/llvmc2/
    llvm/trunk/tools/llvmc2/Common.td
    llvm/trunk/tools/llvmc2/Core.cpp
    llvm/trunk/tools/llvmc2/Core.h
    llvm/trunk/tools/llvmc2/Example.td
    llvm/trunk/tools/llvmc2/ExampleWithOpt.td
    llvm/trunk/tools/llvmc2/Makefile
    llvm/trunk/tools/llvmc2/Tools.cpp
    llvm/trunk/tools/llvmc2/Tools.h
    llvm/trunk/tools/llvmc2/Tools.td
    llvm/trunk/tools/llvmc2/Utility.cpp
    llvm/trunk/tools/llvmc2/Utility.h
    llvm/trunk/tools/llvmc2/doc/
    llvm/trunk/tools/llvmc2/doc/LLVMC-Enhancements.rst
    llvm/trunk/tools/llvmc2/doc/LLVMCC-Tutorial.rst
    llvm/trunk/tools/llvmc2/llvmcc.cpp
    llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.cpp
    llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.h
Modified:
    llvm/trunk/include/llvm/ADT/IntrusiveRefCntPtr.h
    llvm/trunk/tools/Makefile
    llvm/trunk/utils/TableGen/TableGen.cpp

Modified: llvm/trunk/include/llvm/ADT/IntrusiveRefCntPtr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/IntrusiveRefCntPtr.h?rev=48699&r1=48698&r2=48699&view=diff

==============================================================================
--- llvm/trunk/include/llvm/ADT/IntrusiveRefCntPtr.h (original)
+++ llvm/trunk/include/llvm/ADT/IntrusiveRefCntPtr.h Sun Mar 23 03:57:20 2008
@@ -222,4 +222,4 @@
 
 } // end namespace llvm
 
-#endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR
\ No newline at end of file
+#endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR

Modified: llvm/trunk/tools/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=48699&r1=48698&r2=48699&view=diff

==============================================================================
--- llvm/trunk/tools/Makefile (original)
+++ llvm/trunk/tools/Makefile Sun Mar 23 03:57:20 2008
@@ -16,7 +16,7 @@
                  llc llvm-ranlib llvm-ar llvm-nm \
                  llvm-ld llvmc llvm-prof llvm-link \
 		 lli gccas gccld llvm-extract llvm-db llvm2cpp \
-		 bugpoint llvm-bcanalyzer llvm-stub
+		 bugpoint llvm-bcanalyzer llvm-stub llvmc2
 
 
 include $(LEVEL)/Makefile.config

Added: llvm/trunk/tools/llvmc2/Common.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Common.td?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Common.td (added)
+++ llvm/trunk/tools/llvmc2/Common.td Sun Mar 23 03:57:20 2008
@@ -0,0 +1,63 @@
+//===- Tools.td - Common definitions for LLVMCC  -----------*- tablegen -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains common definitions used in llvmcc tool description files.
+//
+//===----------------------------------------------------------------------===//
+
+class Tool<list<dag> l> {
+      list<dag> properties = l;
+}
+
+// Possible Tool properties
+
+def in_language;
+def out_language;
+def output_suffix;
+def cmd_line;
+def join;
+def sink;
+
+// Possible option types
+
+def switch_option;
+def parameter_option;
+def parameter_list_option;
+def prefix_option;
+def prefix_list_option;
+
+// Possible option properties
+
+def append_cmd;
+def forward;
+def stop_compilation;
+def unpack_values;
+def help;
+def required;
+
+// Map from suffixes to language names
+
+class LangToSuffixes<string str, list<string> lst> {
+      string lang = str;
+      list<string> suffixes = lst;
+}
+
+class LanguageMap<list<LangToSuffixes> lst> {
+      list<LangToSuffixes> map = lst;
+}
+
+// Toolchain classes
+
+class ToolChain <list<Tool> lst> {
+      list <Tool> tools = lst;
+}
+
+class ToolChains <list<ToolChain> lst> {
+      list<ToolChain> chains = lst;
+}

Added: llvm/trunk/tools/llvmc2/Core.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Core.cpp?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Core.cpp (added)
+++ llvm/trunk/tools/llvmc2/Core.cpp Sun Mar 23 03:57:20 2008
@@ -0,0 +1,115 @@
+//===--- Core.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Core driver abstractions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Core.h"
+#include "Utility.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <algorithm>
+#include <iostream>
+#include <stdexcept>
+
+using namespace llvm;
+using namespace llvmcc;
+
+extern cl::list<std::string> InputFilenames;
+extern cl::opt<std::string> OutputFilename;
+extern cl::opt<bool> VerboseMode;
+
+namespace {
+  void print_string (const std::string& str) {
+    std::cerr << str << ' ';
+  }
+}
+
+int llvmcc::Action::Execute() {
+  if (VerboseMode) {
+    std::cerr << Command_ << " ";
+    std::for_each(Args_.begin(), Args_.end(), print_string);
+    std::cerr << '\n';
+  }
+  return ExecuteProgram(Command_, Args_);
+}
+
+int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
+  sys::Path In(InputFilenames.at(0)), Out;
+
+  // Find out which language corresponds to the suffix of the first input file
+  LanguageMap::const_iterator Lang = ExtsToLangs.find(In.getSuffix());
+  if (Lang == ExtsToLangs.end())
+    throw std::runtime_error("Unknown suffix!");
+
+  // Find the toolchain corresponding to this language
+  ToolChainMap::const_iterator ToolsIt = ToolChains.find(Lang->second);
+  if (ToolsIt == ToolChains.end())
+    throw std::runtime_error("Unknown language!");
+  ToolChain Tools = ToolsIt->second;
+
+  PathVector JoinList;
+
+  for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
+        E = InputFilenames.end(); B != E; ++B) {
+    In = sys::Path(*B);
+
+    // Pass input file through the toolchain
+    for (ToolChain::const_iterator B = Tools.begin(), E = Tools.end();
+         B != E; ++B) {
+
+      const Tool* CurTool = B->getPtr();
+
+      // Is this the last step in the chain?
+      if (llvm::next(B) == E || CurTool->IsLast()) {
+        JoinList.push_back(In);
+        break;
+      }
+      else {
+        Out = tempDir;
+        Out.appendComponent(In.getBasename());
+        Out.appendSuffix(CurTool->OutputSuffix());
+        Out.makeUnique(true, NULL);
+        Out.eraseFromDisk();
+      }
+
+      if (CurTool->GenerateAction(In, Out).Execute() != 0)
+        throw std::runtime_error("Tool returned error code!");
+
+      In = Out; Out.clear();
+    }
+  }
+
+  // Pass .o files to linker
+  const Tool* JoinNode = (--Tools.end())->getPtr();
+
+  // If the final output name is empty, set it to "a.out"
+  if (!OutputFilename.empty()) {
+    Out = sys::Path(OutputFilename);
+  }
+  else {
+    Out = sys::Path("a");
+    Out.appendSuffix(JoinNode->OutputSuffix());
+  }
+
+  if (JoinNode->GenerateAction(JoinList, Out).Execute() != 0)
+    throw std::runtime_error("Tool returned error code!");
+
+  return 0;
+}
+
+void llvmcc::Tool::UnpackValues (const std::string& from,
+                                 std::vector<std::string>& to) const {
+  SplitString(from, to, ",");
+}
+

Added: llvm/trunk/tools/llvmc2/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Core.h?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Core.h (added)
+++ llvm/trunk/tools/llvmc2/Core.h Sun Mar 23 03:57:20 2008
@@ -0,0 +1,83 @@
+//===--- Core.h - The LLVM Compiler Driver ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Core driver abstractions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMCC_CORE_H
+#define LLVM_TOOLS_LLVMCC_CORE_H
+
+#include "Utility.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/System/Path.h"
+
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+// Core functionality
+
+namespace llvmcc {
+
+  typedef std::vector<llvm::sys::Path> PathVector;
+  typedef llvm::StringMap<std::string> LanguageMap;
+
+  class Action {
+    std::string Command_;
+    std::vector<std::string> Args_;
+  public:
+    Action (std::string const& C,
+            std::vector<std::string> const& A)
+      : Command_(C), Args_(A)
+    {}
+
+    int Execute();
+  };
+
+  class Tool : public llvm::RefCountedBaseVPTR<Tool> {
+  public:
+    virtual Action GenerateAction (PathVector const& inFiles,
+                                  llvm::sys::Path const& outFile) const = 0;
+
+    virtual Action GenerateAction (llvm::sys::Path const& inFile,
+                                  llvm::sys::Path const& outFile) const = 0;
+
+    virtual std::string Name() const = 0;
+    virtual std::string InputLanguage() const = 0;
+    virtual std::string OutputLanguage() const = 0;
+    virtual std::string OutputSuffix() const = 0;
+
+    virtual bool IsLast() const = 0;
+    virtual bool IsJoin() const = 0;
+
+    // Helper function that is called by the auto-generated code
+    // Splits strings of the form ",-foo,-bar,-baz"
+    // TOFIX: find a better name
+    void UnpackValues (std::string const& from,
+                       std::vector<std::string>& to) const;
+
+    virtual ~Tool()
+    {}
+  };
+
+  typedef std::vector<llvm::IntrusiveRefCntPtr<Tool> > ToolChain;
+  typedef llvm::StringMap<ToolChain> ToolChainMap;
+
+  struct CompilationGraph {
+    ToolChainMap ToolChains;
+    LanguageMap ExtsToLangs;
+
+    int Build(llvm::sys::Path const& tempDir) const;
+  };
+}
+
+#endif // LLVM_TOOLS_LLVMCC_CORE_H

Added: llvm/trunk/tools/llvmc2/Example.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Example.td?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Example.td (added)
+++ llvm/trunk/tools/llvmc2/Example.td Sun Mar 23 03:57:20 2008
@@ -0,0 +1,24 @@
+//===- Example.td - LLVMCC toolchain descriptions  ---------*- tablegen -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains toolchain descriptions used by llvmcc.
+//
+//===----------------------------------------------------------------------===//
+
+include "Common.td"
+include "Tools.td"
+
+// Toolchains
+
+def ToolChains : ToolChains<[
+    ToolChain<[llvm_gcc_c, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+    ToolChain<[llvm_gcc_cpp, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+    ToolChain<[llvm_as, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+    ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
+    ]>;

Added: llvm/trunk/tools/llvmc2/ExampleWithOpt.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/ExampleWithOpt.td?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/ExampleWithOpt.td (added)
+++ llvm/trunk/tools/llvmc2/ExampleWithOpt.td Sun Mar 23 03:57:20 2008
@@ -0,0 +1,24 @@
+//===- ExampleWithOpt.td - LLVMCC toolchain descriptions  --*- tablegen -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains toolchain descriptions used by llvmcc.
+//
+//===----------------------------------------------------------------------===//
+
+include "Common.td"
+include "Tools.td"
+
+// Toolchains
+
+def ToolChains : ToolChains<[
+    ToolChain<[llvm_gcc_c, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+    ToolChain<[llvm_gcc_cpp, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+    ToolChain<[llvm_as, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+    ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
+    ]>;

Added: llvm/trunk/tools/llvmc2/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Makefile?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Makefile (added)
+++ llvm/trunk/tools/llvmc2/Makefile Sun Mar 23 03:57:20 2008
@@ -0,0 +1,32 @@
+##===- tools/llvmcc/Makefile -------------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open
+# Source License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../..
+TOOLNAME = llvmc2
+BUILT_SOURCES = Tools.inc
+LINK_COMPONENTS = support system
+REQUIRES_EH := 1
+
+include $(LEVEL)/Makefile.common
+
+TOOLS_TARGET=default
+ifeq ($(TOOLS_TARGET), default)
+	TOOLS_SOURCE=Example.td
+else
+	TOOLS_SOURCE=ExampleWithOpt.td
+endif
+
+# TOFIX: integrate this part into Makefile.rules?
+# The degree of horrorshowness in that file is too much for me atm.
+$(ObjDir)/Tools.inc.tmp: $(TOOLS_SOURCE) $(ObjDir)/.dir
+	$(Echo) "Building LLVMCC configuration library with tblgen"
+	$(Verb) $(TableGen) -gen-llvmcc -o $@ $<
+
+Tools.inc : $(ObjDir)/Tools.inc.tmp
+	$(Verb) $(CMP) -s $@ $< || $(CP) $< $@
+

Added: llvm/trunk/tools/llvmc2/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Tools.cpp?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Tools.cpp (added)
+++ llvm/trunk/tools/llvmc2/Tools.cpp Sun Mar 23 03:57:20 2008
@@ -0,0 +1,28 @@
+//===--- Tools.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Auto-generated tool descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "Core.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace llvmcc;
+
+// Include the auto-generated file
+#include "Tools.inc"

Added: llvm/trunk/tools/llvmc2/Tools.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Tools.h?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Tools.h (added)
+++ llvm/trunk/tools/llvmc2/Tools.h Sun Mar 23 03:57:20 2008
@@ -0,0 +1,26 @@
+//===--- Tools.h - The LLVM Compiler Driver ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Auto-generated tool descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMCC_TOOLS_H
+#define LLVM_TOOLS_LLVMCC_TOOLS_H
+
+#include "Core.h"
+
+namespace llvmcc {
+
+  void PopulateLanguageMap(LanguageMap& language_map);
+  void PopulateCompilationGraph(CompilationGraph& tools);
+
+}
+
+#endif //LLVM_TOOLS_LLVMCC_TOOLS_H

Added: llvm/trunk/tools/llvmc2/Tools.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Tools.td?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Tools.td (added)
+++ llvm/trunk/tools/llvmc2/Tools.td Sun Mar 23 03:57:20 2008
@@ -0,0 +1,87 @@
+//===- Tools.td - Tools description for the LLVMCC  --------*- tablegen -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains descriptions of the various build tools run by llvmcc.
+//
+//===----------------------------------------------------------------------===//
+
+// Open issue: should we use DAG lists in Tool specifications
+// or change to something like
+// def LLVMGccC : < Tool<
+// [ InLanguage<"c">,
+//   PrefixListOption<"Wl", [UnpackValues, PropertyName<Arg>, ...]>
+//  ...] ?
+// DAG lists look more aesthetically pleasing to me.
+
+def llvm_gcc_c : Tool<
+[(in_language "c"),
+ (out_language "llvm-assembler"),
+ (output_suffix "bc"),
+ (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE -emit-llvm"),
+ (sink)
+]>;
+
+def llvm_gcc_cpp : Tool<
+[(in_language "c++"),
+ (out_language "llvm-assembler"),
+ (output_suffix "bc"),
+ (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
+ (sink)
+]>;
+
+def opt : Tool<
+[(in_language "llvm-bitcode"),
+ (out_language "llvm-bitcode"),
+ (output_suffix "bc"),
+ (cmd_line "opt $INFILE -o $OUTFILE")
+]>;
+
+def llvm_as : Tool<
+[(in_language "llvm-assembler"),
+ (out_language "llvm-bitcode"),
+ (output_suffix "bc"),
+ (cmd_line "llvm-as $INFILE -o $OUTFILE")
+]>;
+
+def llc : Tool<
+[(in_language "llvm-bitcode"),
+ (out_language "assembler"),
+ (output_suffix "s"),
+ (cmd_line "llc $INFILE -o $OUTFILE")
+]>;
+
+def llvm_gcc_assembler : Tool<
+[(in_language "assembler"),
+ (out_language "object-code"),
+ (output_suffix "o"),
+ (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE"),
+ (prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
+]>;
+
+def llvm_gcc_linker : Tool<
+[(in_language "object-code"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
+ (join),
+ (prefix_list_option "L", (forward), (help "add a directory to link path")),
+ (prefix_list_option "l", (forward), (help "search a library when linking")),
+ (prefix_list_option "Wl", (unpack_values), (help "pass options to linker"))
+]>;
+
+// Language map
+
+def LanguageMap : LanguageMap<
+    [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
+     LangToSuffixes<"c", ["c"]>,
+     LangToSuffixes<"assembler", ["s"]>,
+     LangToSuffixes<"llvm-assembler", ["ll"]>,
+     LangToSuffixes<"llvm-bitcode", ["bc"]>,
+     LangToSuffixes<"object-code", ["o"]>,
+     LangToSuffixes<"executable", ["out"]>]>;

Added: llvm/trunk/tools/llvmc2/Utility.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Utility.cpp?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Utility.cpp (added)
+++ llvm/trunk/tools/llvmc2/Utility.cpp Sun Mar 23 03:57:20 2008
@@ -0,0 +1,39 @@
+//===--- Utility.cpp - The LLVM Compiler Driver -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Various helper and utility functions - implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Utility.h"
+
+#include "llvm/System/Program.h"
+
+#include <stdexcept>
+
+using namespace llvm;
+
+int llvmcc::ExecuteProgram(const std::string& name,
+                           const std::vector<std::string>& args) {
+  sys::Path prog = sys::Program::FindProgramByName(name);
+
+  if (prog.isEmpty())
+    throw std::runtime_error("Can't find program '" + name + "'");
+  if (!prog.canExecute())
+    throw std::runtime_error("Program '" + name + "' is not executable.");
+
+  // Invoke the program
+  std::vector<const char*> argv((args.size()+2));
+  argv[0] = name.c_str();
+  for (unsigned i = 1; i <= args.size(); ++i)
+    argv[i] = args[i-1].c_str();
+  argv[args.size()+1] = 0;  // null terminate list.
+
+  return sys::Program::ExecuteAndWait(prog, &argv[0]);
+}

Added: llvm/trunk/tools/llvmc2/Utility.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/Utility.h?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/Utility.h (added)
+++ llvm/trunk/tools/llvmc2/Utility.h Sun Mar 23 03:57:20 2008
@@ -0,0 +1,27 @@
+//===--- Utility.h - The LLVM Compiler Driver -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Various helper and utility functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMCC_UTILITY_H
+#define LLVM_TOOLS_LLVMCC_UTILITY_H
+
+#include <string>
+#include <vector>
+
+namespace llvmcc {
+
+  int ExecuteProgram (const std::string& name,
+                      const std::vector<std::string>& arguments);
+
+}
+
+#endif // LLVM_TOOLS_LLVMCC_UTILITY_H

Added: llvm/trunk/tools/llvmc2/doc/LLVMC-Enhancements.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/doc/LLVMC-Enhancements.rst?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/doc/LLVMC-Enhancements.rst (added)
+++ llvm/trunk/tools/llvmc2/doc/LLVMC-Enhancements.rst Sun Mar 23 03:57:20 2008
@@ -0,0 +1,270 @@
+Introduction
+============
+
+A complete rewrite of the LLVMC compiler driver is proposed, aimed at
+making it more configurable and useful.
+
+Motivation
+==========
+
+As it stands, current version of LLVMC does not meet its stated goals
+of configurability and extensibility and is therefore not used
+much. The need for enhancements in LLVMC is also reflected in [1]_. The
+proposed rewrite will fix the aforementioned deficiences and provide
+an extensible, future-proof solution.
+
+Design
+======
+
+A compiler driver's job is essentially to find a way how to transform
+a set of input files into a set of targets, depending on the
+user-provided options. Since several ways of transformation can exist
+potentially, it's natural to use a directed graph to represent all of
+them. In this graph, nodes are tools (for example, ``gcc -S`` is a tool
+that generates assembly from C language files) and edges between them
+mean that the output of one tool can be given as input to another (as
+in ``gcc -S -o - file.c | as``). We'll call this graph the compilation
+graph.
+
+The proposed design revolves around the compilation graph and the
+following core abstractions:
+
+- Target - An (intermediate) compilation target.
+
+- Action - A shell command template that represents basic compilation
+  transformation(example: ``gcc -S $INPUT_FILE -o $OUTPUT_FILE``).
+
+- Tool - Encapsulates information about a concrete tool used in the
+  compilation process, produces Actions. Operation depends on
+  command-line options provided by the user.
+
+- GraphBuilder - Constructs the compilation graph, operation depends
+  on command-line options.
+
+- GraphTraverser - Traverses the compilation graph and constructs a
+  sequence of Actions needed to build the target file, operation
+  depends on command-line options.
+
+A high-level view of the compilation process:
+
+  1. Configuration libraries (see below) are loaded in and the
+  compilation graph is constructed from the tool descriptions.
+
+  2. Information about possible options is gathered from (the nodes of)
+  the compilation graph.
+
+  3. Options are parsed based on data gathered in step 2.
+
+  4. A sequence of Actions needed to build the target is constructed
+  using the compilation graph and provided options.
+
+  5. The resulting action sequence is executed.
+
+Extensibility
+==============
+
+To make this design extensible, TableGen [2]_ will be used for
+automatic generation of the Tool classes. Users wanting to customize
+LLVMC will need to write a configuration library consisting of a set
+of TableGen descriptions of compilation tools plus a number of hooks
+that influence compilation graph construction and traversal. LLVMC
+will have the ability to load user configuration libraries at runtime;
+in fact, its own basic functionality will be implemented as a
+configuration library.
+
+TableGen specification example
+------------------------------
+
+This small example specifies a Tool that converts C source to object
+files. Note that it is only a mock-up of inteded functionality, not a
+final specification::
+
+    def GCC : Tool<
+     GCCProperties, // Properties of this tool
+     GCCOptions     // Options description for this tool
+    >;
+
+    def GCCProperties : ToolProperties<[
+     ToolName<"GCC">,
+     InputLanguageName<"C">,
+     OutputLanguageName<"Object-Code">
+     InputFileExtension<"c">,
+     OutputFileExtension<"o">,
+     CommandFormat<"gcc -c $OPTIONS $FILES">
+    ]>;
+
+    def GCCOptions : ToolOptions<[
+     Option<
+       "-Wall",                 // Option name
+       [None],                  // Allowed values
+       [AddOption<"-Wall">]>,   // Action
+
+     Option<
+       "-Wextra",               // Option name
+       [None],                  // Allowed values
+       [AddOption<"-Wextra">]>, // Action
+
+     Option<
+       "-W",                 // Option name
+       [None],               // Allowed values
+       [AddOption<"-W">]>,   // Action
+
+     Option<
+       "-D",        // Option name
+       [AnyString], // Allowed values
+
+       [AddOptionWithArgument<"-D",GetOptionArgument<"-D">>]
+       // Action:
+       // If the driver was given option "-D<argument>", add
+       // option "-D" with the same argument to the invocation string of
+       // this tool.
+       >
+
+     ]>;
+
+Example of generated code
+-------------------------
+
+The specification above compiles to the following code (again, it's a
+mock-up)::
+
+    class GCC : public Tool {
+
+    public:
+
+      GCC() { //... }
+
+     // Properties
+
+      static const char* ToolName = "GCC";
+      static const char* InputLanguageName = "C";
+      static const char* OutputLanguageName = "Object-Code";
+      static const char* InputFileExtension = "c";
+      static const char* OutputFileExtension = "o";
+      static const char* CommandFormat = "gcc -c $OPTIONS $FILES";
+
+     // Options
+
+     OptionsDescription SupportedOptions() {
+       OptionsDescription supportedOptions;
+
+       supportedOptions.Add(Option("-Wall"));
+       supportedOptions.Add(Option("-Wextra"));
+       supportedOptions.Add(Option("-W"));
+       supportedOptions.Add(Option("-D", AllowedArgs::ANY_STRING));
+
+       return supportedOptions;
+     }
+
+     Action GenerateAction(Options providedOptions) {
+       Action generatedAction(CommandFormat); Option curOpt;
+
+       curOpt = providedOptions.Get("-D");
+       if (curOpt) {
+          assert(curOpt.HasArgument());
+          generatedAction.AddOption(Option("-D", curOpt.GetArgument()));
+       }
+
+       curOpt = providedOptions.Get("-Wall");
+       if (curOpt)
+         generatedAction.AddOption(Option("-Wall"));
+
+       curOpt = providedOptions.Get("-Wextra");
+       if (curOpt)
+         generatedAction.AddOption(Option("-Wall"));
+
+       curOpt = providedOptions.Get("-W");
+       if (curOpt)
+         generatedAction.AddOption(Option("-Wall")); }
+
+       return generatedAction;
+     }
+
+    };
+
+    // defined somewhere...
+
+    class Action { public: void AddOption(const Option& opt) {...}
+    int Run(const Filenames& fnms) {...}
+
+    }
+
+Option handling
+===============
+
+Since one of the main tasks of the compiler driver is to correctly
+handle user-provided options, it is important to define this process
+in exact way. The intent of the proposed scheme is to function as a
+drop-in replacement for GCC.
+
+Option syntax
+-------------
+
+Option syntax is specified by the following formal grammar::
+
+        <command-line>      ::=  <option>*
+        <option>            ::=  <positional-option> | <named-option>
+        <named-option>      ::=  -[-]<option-name>[<delimeter><option-argument>]
+        <delimeter>         ::=  ',' | '=' | ' '
+        <positional-option> ::=  <string>
+        <option-name>       ::=  <string>
+        <option-argument>   ::=  <string>
+
+This roughly corresponds to the GCC option syntax. Note that grouping
+of short options(as in ``ls -la``) is forbidden.
+
+Example::
+
+        llvmc -O3 -Wa,-foo,-bar -pedantic -std=c++0x a.c b.c c.c
+
+Option arguments can also have special forms: for example, an argument
+can be a comma-separated list (like in -Wa,-foo,-bar). In such cases,
+it's up to the option handler to parse the argument.
+
+Option semantics
+----------------
+
+According to their meaning, options are classified into following
+categories:
+
+- Global options - Options that influence compilation graph
+  construction/traversal. Example: -E (stop after preprocessing).
+
+- Local options - Options that influence one or several Actions in
+  the generated action sequence. Example: -O3 (turn on optimization).
+
+- Prefix options - Options that influence meaning of the following
+  command-line arguments. Example: -x language (specify language for
+  the input files explicitly). Prefix options can be local or global.
+
+- Built-in options - Options that are hard-coded into
+  driver. Examples: --help, -o file/-pipe (redirect output). Can be
+  local or global.
+
+Naming
+======
+
+Since the compiler driver, as a single point of access to the LLVM
+tool set, is a very often used tool, it would be desirable to make its name
+as short and easy to type as possible. Some possible names are 'llcc' or
+'lcc', by analogy with gcc.
+
+
+Issues
+======
+
+1. Should global-options-influencing hooks be written by hand or
+   auto-generated from TableGen specifications?
+
+2. More?
+
+References
+==========
+
+.. [1] LLVM Bug#686
+
+       http://llvm.org/bugs/show_bug.cgi?id=686
+
+.. [2] TableGen Fundamentals
+
+       http://llvm.org/docs/TableGenFundamentals.html

Added: llvm/trunk/tools/llvmc2/doc/LLVMCC-Tutorial.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/doc/LLVMCC-Tutorial.rst?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/doc/LLVMCC-Tutorial.rst (added)
+++ llvm/trunk/tools/llvmc2/doc/LLVMCC-Tutorial.rst Sun Mar 23 03:57:20 2008
@@ -0,0 +1,153 @@
+Tutorial - Writing LLVMCC Configuration files
+=============================================
+
+LLVMCC is a generic compiler driver(just like ``gcc``), designed to be
+customizable and extensible. Its job is essentially to transform a set
+of input files into a set of targets, depending on configuration rules
+and user options. This tutorial describes how one can write
+configuration files for ``llvmcc``.
+
+Since LLVMCC uses TableGen [1]_ as the language of its configuration
+files, you need to be familiar with it.
+
+Describing a toolchain
+----------------------
+
+The main concept that ``llvmcc`` operates with is a *toolchain*, which
+is just a list of tools that process input files in a pipeline-like
+fashion. Toolchain definitions look like this::
+
+   def ToolChains : ToolChains<[
+       ToolChain<[llvm_gcc_c, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+       ToolChain<[llvm_gcc_cpp, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
+       ...
+       ]>;
+
+Every configuration file should have a single toolchains list called
+``ToolChains``.
+
+At the time of writing, ``llvmcc`` does not support mixing various
+toolchains together - in other words, all input files should be in the
+same language.
+
+Another temporary limitation is that every toolchain should end with a
+"join" node - a linker-like program that combines its inputs into a
+single output file.
+
+Describing a tool
+-----------------
+
+A single element of a toolchain is a tool. A tool definition looks
+like this (taken from the Tools.td file)::
+
+  def llvm_gcc_cpp : Tool<[
+      (in_language "c++"),
+      (out_language "llvm-assembler"),
+      (output_suffix "bc"),
+      (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
+      (sink)
+      ]>;
+
+This defines a new tool called ``llvm_gcc_cpp``, which is an alias for
+``llvm-g++``. As you can see, a tool definition is just a list of
+properties; most of them should be self-evident. The ``sink`` property
+means that this tool should be passed all command-line options that
+aren't handled by the other tools.
+
+The complete list of the currently implemented tool properties follows:
+
+* Possible tool properties:
+  - in_language - input language name.
+
+  - out_language - output language name.
+
+  - output_suffix - output file suffix.
+
+  - cmd_line - the actual command used to run the tool. You can use
+    ``$INFILE`` and ``$OUTFILE`` variables.
+
+  - join - this tool is a "join node" in the graph, i.e. it gets a
+    list of input files and joins them together. Used for linkers.
+
+  - sink - all command-line options that are not handled by other
+    tools are passed to this tool.
+
+The next tool definition is slightly more complex::
+
+  def llvm_gcc_linker : Tool<[
+      (in_language "object-code"),
+      (out_language "executable"),
+      (output_suffix "out"),
+      (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
+      (join),
+      (prefix_list_option "L", (forward), (help "add a directory to link path")),
+      (prefix_list_option "l", (forward), (help "search a library when linking")),
+      (prefix_list_option "Wl", (unpack_values), (help "pass options to linker"))
+      ]>;
+
+This tool has a "join" property, which means that it behaves like a
+linker (because of that this tool should be the last in the
+toolchain). This tool also defines several command-line options: ``-l``,
+``-L`` and ``-Wl`` which have their usual meaning. An option has two
+attributes: a name and a (possibly empty) list of properties. All
+currently implemented option types and properties are described below:
+
+* Possible option types:
+   - switch_option - a simple boolean switch, for example ``-time``.
+
+   - parameter_option - option that takes an argument, for example ``-std=c99``;
+
+   - parameter_list_option - same as the above, but more than one
+     occurence of the option is allowed.
+
+   - prefix_option - same as the parameter_option, but the option name
+     and parameter value are not separated.
+
+   - prefix_list_option - same as the above, but more than one
+     occurence of the option is allowed; example: ``-lm -lpthread``.
+
+* Possible option properties:
+   - append_cmd - append a string to the tool invocation command.
+
+   - forward - forward this option unchanged.
+
+   - stop_compilation - stop compilation after this phase.
+
+   - unpack_values - used for for splitting and forwarding
+     comma-separated lists of options, e.g. ``-Wa,-foo=bar,-baz`` is
+     converted to ``-foo=bar -baz`` and appended to the tool invocation
+     command.
+
+   - help - help string associated with this option.
+
+   - required - this option is obligatory.
+
+Language map
+------------
+
+One last bit that you probably should change is the language map,
+which defines mappings between language names and file extensions. It
+is used internally to choose the proper toolchain based on the names
+of the input files. Language map definition is located in the file
+``Tools.td`` and looks like this::
+
+    def LanguageMap : LanguageMap<
+        [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
+         LangToSuffixes<"c", ["c"]>,
+         ...
+        ]>;
+
+
+Putting it all together
+-----------------------
+
+Since at the time of writing LLVMCC does not support on-the-fly
+reloading of the configuration, the only way to test your changes is
+to recompile the program. To do this, ``cd`` to the source code
+directory and run ``make``.
+
+References
+==========
+
+.. [1] TableGen Fundamentals
+       http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html

Added: llvm/trunk/tools/llvmc2/llvmcc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc2/llvmcc.cpp?rev=48699&view=auto

==============================================================================
--- llvm/trunk/tools/llvmc2/llvmcc.cpp (added)
+++ llvm/trunk/tools/llvmc2/llvmcc.cpp Sun Mar 23 03:57:20 2008
@@ -0,0 +1,73 @@
+//===--- llvmcc.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This tool provides a single point of access to the LLVM
+//  compilation tools.  It has many options. To discover the options
+//  supported please refer to the tools' manual page or run the tool
+//  with the --help option.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Core.h"
+#include "Utility.h"
+#include "Tools.h"
+
+#include "llvm/System/Path.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <string>
+
+using namespace llvm;
+using namespace llvmcc;
+
+// These variables are also used in Core.cpp,
+// so they should have external linkage.
+cl::list<std::string> InputFilenames(cl::Positional,
+                                     cl::desc("<input file>"), cl::OneOrMore);
+cl::opt<std::string> OutputFilename("o", cl::desc("Output file name"),
+                                    cl::value_desc("file"));
+cl::opt<bool> VerboseMode("v", cl::desc("Enable verbose mode"));
+
+
+namespace {
+  int BuildTargets(const CompilationGraph& graph) {
+    int ret;
+    sys::Path tempDir(sys::Path::GetTemporaryDirectory());
+
+    try {
+      ret = graph.Build(tempDir);
+    }
+    catch(...) {
+      tempDir.eraseFromDisk(true);
+      throw;
+    }
+
+    tempDir.eraseFromDisk(true);
+    return ret;
+  }
+}
+
+int main(int argc, char** argv) {
+  try {
+    CompilationGraph graph;
+
+    cl::ParseCommandLineOptions(argc, argv,
+                                "LLVM Compiler Driver(Work In Progress)");
+    PopulateCompilationGraph(graph);
+    return BuildTargets(graph);
+  }
+  catch(const std::exception& ex) {
+    std::cerr << ex.what() << '\n';
+  }
+  catch(...) {
+    std::cerr << "Unknown error!\n";
+  }
+}

Added: llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.cpp?rev=48699&view=auto

==============================================================================
--- llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.cpp (added)
+++ llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.cpp Sun Mar 23 03:57:20 2008
@@ -0,0 +1,935 @@
+//===- 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() {}
+
+  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
+}

Added: llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.h?rev=48699&view=auto

==============================================================================
--- llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.h (added)
+++ llvm/trunk/utils/TableGen/LLVMCCConfigurationEmitter.h Sun Mar 23 03:57:20 2008
@@ -0,0 +1,30 @@
+//===- 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVMCCCONF_EMITTER_H
+#define LLVMCCCONF_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+  class LLVMCCConfigurationEmitter : public TableGenBackend {
+    RecordKeeper &Records;
+  public:
+    explicit LLVMCCConfigurationEmitter(RecordKeeper &R) : Records(R) {}
+
+    // run - Output the asmwriter, returning true on failure.
+    void run(std::ostream &o);
+  };
+}
+
+#endif //LLVMCCCONF_EMITTER_H

Modified: llvm/trunk/utils/TableGen/TableGen.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TableGen.cpp?rev=48699&r1=48698&r2=48699&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TableGen.cpp (original)
+++ llvm/trunk/utils/TableGen/TableGen.cpp Sun Mar 23 03:57:20 2008
@@ -31,6 +31,7 @@
 #include "DAGISelEmitter.h"
 #include "SubtargetEmitter.h"
 #include "IntrinsicEmitter.h"
+#include "LLVMCCConfigurationEmitter.h"
 #include <algorithm>
 #include <cstdio>
 #include <fstream>
@@ -41,11 +42,12 @@
   PrintRecords,
   GenEmitter,
   GenRegisterEnums, GenRegister, GenRegisterHeader,
-  GenInstrEnums, GenInstrs, GenAsmWriter, 
+  GenInstrEnums, GenInstrs, GenAsmWriter,
   GenCallingConv,
   GenDAGISel,
   GenSubtarget,
   GenIntrinsic,
+  GenLLVMCCConf,
   PrintEnums
 };
 
@@ -76,6 +78,8 @@
                                "Generate subtarget enumerations"),
                     clEnumValN(GenIntrinsic, "gen-intrinsic",
                                "Generate intrinsic information"),
+                    clEnumValN(GenLLVMCCConf, "gen-llvmcc",
+                               "Generate LLVMCC configuration library"),
                     clEnumValN(PrintEnums, "print-enums",
                                "Print enum values for a class"),
                     clEnumValEnd));
@@ -180,6 +184,9 @@
     case GenIntrinsic:
       IntrinsicEmitter(Records).run(*Out);
       break;
+    case GenLLVMCCConf:
+      LLVMCCConfigurationEmitter(Records).run(*Out);
+      break;
     case PrintEnums:
     {
       std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);





More information about the llvm-commits mailing list