diff options
Diffstat (limited to 'lib/CompilerDriver')
-rw-r--r-- | lib/CompilerDriver/Action.cpp | 10 | ||||
-rw-r--r-- | lib/CompilerDriver/BuiltinOptions.cpp | 55 | ||||
-rw-r--r-- | lib/CompilerDriver/CompilationGraph.cpp | 33 | ||||
-rw-r--r-- | lib/CompilerDriver/Main.cpp | 130 | ||||
-rw-r--r-- | lib/CompilerDriver/Makefile | 32 | ||||
-rw-r--r-- | lib/CompilerDriver/Tool.cpp | 6 |
6 files changed, 241 insertions, 25 deletions
diff --git a/lib/CompilerDriver/Action.cpp b/lib/CompilerDriver/Action.cpp index 816f793..5fd63ee 100644 --- a/lib/CompilerDriver/Action.cpp +++ b/lib/CompilerDriver/Action.cpp @@ -13,10 +13,8 @@ #include "llvm/CompilerDriver/Action.h" #include "llvm/CompilerDriver/BuiltinOptions.h" - +#include "llvm/Support/raw_ostream.h" #include "llvm/System/Program.h" - -#include <iostream> #include <stdexcept> using namespace llvm; @@ -58,15 +56,15 @@ namespace { } void print_string (const std::string& str) { - std::cerr << str << ' '; + errs() << str << ' '; } } int llvmc::Action::Execute() const { if (DryRun || VerboseMode) { - std::cerr << Command_ << " "; + errs() << Command_ << " "; std::for_each(Args_.begin(), Args_.end(), print_string); - std::cerr << '\n'; + errs() << '\n'; } if (DryRun) return 0; diff --git a/lib/CompilerDriver/BuiltinOptions.cpp b/lib/CompilerDriver/BuiltinOptions.cpp new file mode 100644 index 0000000..a3364e8 --- /dev/null +++ b/lib/CompilerDriver/BuiltinOptions.cpp @@ -0,0 +1,55 @@ +//===--- BuiltinOptions.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. +// +//===----------------------------------------------------------------------===// +// +// Definitions of all global command-line option variables. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/BuiltinOptions.h" + +#ifdef ENABLE_LLVMC_DYNAMIC_PLUGINS +#include "llvm/Support/PluginLoader.h" +#endif + +namespace cl = llvm::cl; + +// External linkage here is intentional. + +cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input file>"), + cl::ZeroOrMore); +cl::opt<std::string> OutputFilename("o", cl::desc("Output file name"), + cl::value_desc("file"), cl::Prefix); +cl::list<std::string> Languages("x", + cl::desc("Specify the language of the following input files"), + cl::ZeroOrMore); +cl::opt<bool> DryRun("dry-run", + cl::desc("Only pretend to run commands")); +cl::opt<bool> VerboseMode("v", + cl::desc("Enable verbose mode")); + +cl::opt<bool> CheckGraph("check-graph", + cl::desc("Check the compilation graph for errors"), + cl::Hidden); +cl::opt<bool> WriteGraph("write-graph", + cl::desc("Write compilation-graph.dot file"), + cl::Hidden); +cl::opt<bool> ViewGraph("view-graph", + cl::desc("Show compilation graph in GhostView"), + cl::Hidden); + +cl::opt<SaveTempsEnum::Values> SaveTemps +("save-temps", cl::desc("Keep temporary files"), + cl::init(SaveTempsEnum::Unset), + cl::values(clEnumValN(SaveTempsEnum::Obj, "obj", + "Save files in the directory specified with -o"), + clEnumValN(SaveTempsEnum::Cwd, "cwd", + "Use current working directory"), + clEnumValN(SaveTempsEnum::Obj, "", "Same as 'cwd'"), + clEnumValEnd), + cl::ValueOptional); diff --git a/lib/CompilerDriver/CompilationGraph.cpp b/lib/CompilerDriver/CompilationGraph.cpp index 1212a21..f303943 100644 --- a/lib/CompilerDriver/CompilationGraph.cpp +++ b/lib/CompilerDriver/CompilationGraph.cpp @@ -18,10 +18,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstring> -#include <iostream> #include <iterator> #include <limits> #include <queue> @@ -346,8 +346,8 @@ int CompilationGraph::CheckLanguageNames() const { if (!N2.ToolPtr) { ++ret; - std::cerr << "Error: there is an edge from '" << N1.ToolPtr->Name() - << "' back to the root!\n\n"; + errs() << "Error: there is an edge from '" << N1.ToolPtr->Name() + << "' back to the root!\n\n"; continue; } @@ -363,17 +363,17 @@ int CompilationGraph::CheckLanguageNames() const { if (!eq) { ++ret; - std::cerr << "Error: Output->input language mismatch in the edge '" << - N1.ToolPtr->Name() << "' -> '" << N2.ToolPtr->Name() << "'!\n"; - - std::cerr << "Expected one of { "; + errs() << "Error: Output->input language mismatch in the edge '" + << N1.ToolPtr->Name() << "' -> '" << N2.ToolPtr->Name() + << "'!\n" + << "Expected one of { "; InLangs = N2.ToolPtr->InputLanguages(); for (;*InLangs; ++InLangs) { - std::cerr << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'"); + errs() << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'"); } - std::cerr << " }, but got '" << OutLang << "'!\n\n"; + errs() << " }, but got '" << OutLang << "'!\n\n"; } } @@ -406,9 +406,8 @@ int CompilationGraph::CheckMultipleDefaultEdges() const { } else if (EdgeWeight == MaxWeight) { ++ret; - std::cerr - << "Error: there are multiple maximal edges stemming from the '" - << N.ToolPtr->Name() << "' node!\n\n"; + errs() << "Error: there are multiple maximal edges stemming from the '" + << N.ToolPtr->Name() << "' node!\n\n"; break; } } @@ -440,9 +439,9 @@ int CompilationGraph::CheckCycles() { } if (deleted != NodesMap.size()) { - std::cerr << "Error: there are cycles in the compilation graph!\n" - << "Try inspecting the diagram produced by " - "'llvmc --view-graph'.\n\n"; + errs() << "Error: there are cycles in the compilation graph!\n" + << "Try inspecting the diagram produced by " + << "'llvmc --view-graph'.\n\n"; return 1; } @@ -518,9 +517,9 @@ void CompilationGraph::writeGraph(const std::string& OutputFilename) { std::ofstream O(OutputFilename.c_str()); if (O.good()) { - std::cerr << "Writing '"<< OutputFilename << "' file..."; + errs() << "Writing '"<< OutputFilename << "' file..."; llvm::WriteGraph(O, this); - std::cerr << "done.\n"; + errs() << "done.\n"; O.close(); } else { diff --git a/lib/CompilerDriver/Main.cpp b/lib/CompilerDriver/Main.cpp new file mode 100644 index 0000000..c9c0413 --- /dev/null +++ b/lib/CompilerDriver/Main.cpp @@ -0,0 +1,130 @@ +//===--- Main.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. +// +//===----------------------------------------------------------------------===// +// +// llvmc::Main function - driver entry point. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/BuiltinOptions.h" +#include "llvm/CompilerDriver/CompilationGraph.h" +#include "llvm/CompilerDriver/Error.h" +#include "llvm/CompilerDriver/Plugin.h" + +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Path.h" + +#include <stdexcept> +#include <string> + +namespace cl = llvm::cl; +namespace sys = llvm::sys; +using namespace llvmc; + +namespace { + + sys::Path getTempDir() { + sys::Path tempDir; + + // GCC 4.5-style -save-temps handling. + if (SaveTemps == SaveTempsEnum::Unset) { + tempDir = sys::Path::GetTemporaryDirectory(); + } + else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) { + tempDir = OutputFilename; + + if (!tempDir.exists()) { + std::string ErrMsg; + if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) + throw std::runtime_error(ErrMsg); + } + } + // else if (SaveTemps == Cwd) -> use current dir (leave tempDir empty) + + return tempDir; + } + + /// BuildTargets - A small wrapper for CompilationGraph::Build. + int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) { + int ret; + const sys::Path& tempDir = getTempDir(); + + try { + ret = graph.Build(tempDir, langMap); + } + catch(...) { + if (SaveTemps == SaveTempsEnum::Unset) + tempDir.eraseFromDisk(true); + throw; + } + + if (SaveTemps == SaveTempsEnum::Unset) + tempDir.eraseFromDisk(true); + return ret; + } +} + +namespace llvmc { + +// Sometimes plugins want to condition on the value in argv[0]. +const char* ProgramName; + +int Main(int argc, char** argv) { + try { + LanguageMap langMap; + CompilationGraph graph; + + ProgramName = argv[0]; + + cl::ParseCommandLineOptions + (argc, argv, "LLVM Compiler Driver (Work In Progress)", true); + + PluginLoader Plugins; + Plugins.PopulateLanguageMap(langMap); + Plugins.PopulateCompilationGraph(graph); + + if (CheckGraph) { + int ret = graph.Check(); + if (!ret) + llvm::errs() << "check-graph: no errors found.\n"; + + return ret; + } + + if (ViewGraph) { + graph.viewGraph(); + if (!WriteGraph) + return 0; + } + + if (WriteGraph) { + graph.writeGraph(OutputFilename.empty() + ? std::string("compilation-graph.dot") + : OutputFilename); + return 0; + } + + if (InputFilenames.empty()) { + throw std::runtime_error("no input files"); + } + + return BuildTargets(graph, langMap); + } + catch(llvmc::error_code& ec) { + return ec.code(); + } + catch(const std::exception& ex) { + llvm::errs() << argv[0] << ": " << ex.what() << '\n'; + } + catch(...) { + llvm::errs() << argv[0] << ": unknown error!\n"; + } + return 1; +} + +} // end namespace llvmc diff --git a/lib/CompilerDriver/Makefile b/lib/CompilerDriver/Makefile index e5bf3e1..a5ecfd5 100644 --- a/lib/CompilerDriver/Makefile +++ b/lib/CompilerDriver/Makefile @@ -12,8 +12,36 @@ LEVEL = ../.. # We don't want this library to appear in `llvm-config --libs` output, so its # name doesn't start with "LLVM". -LIBRARYNAME = CompilerDriver -LINK_COMPONENTS = support system +ifeq ($(ENABLE_LLVMC_DYNAMIC),1) + LIBRARYNAME = libCompilerDriver + LLVMLIBS = LLVMSupport.a LLVMSystem.a + LOADABLE_MODULE := 1 +else + LIBRARYNAME = CompilerDriver + LINK_COMPONENTS = support system +endif + REQUIRES_EH := 1 include $(LEVEL)/Makefile.common + +ifeq ($(ENABLE_LLVMC_DYNAMIC_PLUGINS), 1) + CPP.Flags += -DENABLE_LLVMC_DYNAMIC_PLUGINS +endif + +# Copy libCompilerDriver to the bin dir so that llvmc can find it. +ifeq ($(ENABLE_LLVMC_DYNAMIC),1) + +FullLibName = $(LIBRARYNAME)$(SHLIBEXT) + +all-local:: $(ToolDir)/$(FullLibName) + +$(ToolDir)/$(FullLibName): $(LibDir)/$(FullLibName) $(ToolDir)/.dir + $(Echo) Copying $(BuildMode) Shared Library $(FullLibName) to $@ + -$(Verb) $(CP) $< $@ + +clean-local:: + $(Echo) Removing $(BuildMode) Shared Library $(FullLibName) \ + from $(ToolDir) + -$(Verb) $(RM) -f $(ToolDir)/$(FullLibName) +endif diff --git a/lib/CompilerDriver/Tool.cpp b/lib/CompilerDriver/Tool.cpp index e704dd9..7953dd2 100644 --- a/lib/CompilerDriver/Tool.cpp +++ b/lib/CompilerDriver/Tool.cpp @@ -14,11 +14,17 @@ #include "llvm/CompilerDriver/BuiltinOptions.h" #include "llvm/CompilerDriver/Tool.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/System/Path.h" using namespace llvm; using namespace llvmc; +// SplitString is used by derived Tool classes. +typedef void (*SplitStringFunPtr)(const std::string&, + std::vector<std::string>&, const char*); +SplitStringFunPtr ForceLinkageSplitString = &llvm::SplitString; + namespace { sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName, const std::string& Suffix) { |