Add -x option (like in gcc).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50750 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2008-05-06 18:10:53 +00:00
parent 35a85e8453
commit 87416b4cea
5 changed files with 93 additions and 22 deletions

View File

@ -34,7 +34,7 @@ namespace {
if (!prog.canExecute())
throw std::runtime_error("Program '" + name + "' is not executable.");
// Build the command line vector and redirects.
// Build the command line vector and the redirects array.
const sys::Path* redirects[3] = {0,0,0};
sys::Path stdout_redirect;

View File

@ -13,13 +13,14 @@
#include "CompilationGraph.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/GraphWriter.h"
#include <algorithm>
#include <iostream>
#include <iterator>
#include <limits>
#include <queue>
#include <stdexcept>
@ -28,10 +29,13 @@ using namespace llvmc;
extern cl::list<std::string> InputFilenames;
extern cl::opt<std::string> OutputFilename;
extern cl::list<std::string> Languages;
namespace {
// Choose edge that returns
// Go through the list C and find the edge that isEnabled(); if
// there is no such edge, return the default edge; if there is no
// default edge, throw an exception.
template <class C>
const Edge* ChooseEdge(const C& EdgesContainer,
const std::string& NodeName = "root") {
@ -47,7 +51,7 @@ namespace {
else
throw std::runtime_error("Node " + NodeName
+ ": multiple default outward edges found!"
"Most probably a specification error.");
" Most probably a specification error.");
if (E->isEnabled())
return E;
}
@ -57,7 +61,7 @@ namespace {
else
throw std::runtime_error("Node " + NodeName
+ ": no default outward edge found!"
"Most probably a specification error.");
" Most probably a specification error.");
}
}
@ -92,8 +96,8 @@ CompilationGraph::getToolsVector(const std::string& LangName) const
{
tools_map_type::const_iterator I = ToolsMap.find(LangName);
if (I == ToolsMap.end())
throw std::runtime_error("No tools corresponding to " + LangName
+ " found!");
throw std::runtime_error("No tool corresponding to the language "
+ LangName + "found!");
return I->second;
}
@ -121,15 +125,15 @@ void CompilationGraph::insertEdge(const std::string& A, Edge* E) {
B.IncrInEdges();
}
// Make a temporary file named like BaseName-RandomDigits.Suffix
sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
const std::string& Suffix) {
sys::Path Out = TempDir;
Out.appendComponent(BaseName);
Out.appendSuffix(Suffix);
Out.makeUnique(true, NULL);
Out.eraseFromDisk();
return Out;
namespace {
sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
const std::string& Suffix) {
sys::Path Out = TempDir;
Out.appendComponent(BaseName);
Out.appendSuffix(Suffix);
Out.makeUnique(true, NULL);
return Out;
}
}
// Pass input file through the chain until we bump into a Join node or
@ -170,6 +174,9 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
if (CurTool->GenerateAction(In, Out).Execute() != 0)
throw std::runtime_error("Tool returned error code!");
if (Last)
return;
CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
CurNode->Name())->ToolName());
In = Out; Out.clear();
@ -212,8 +219,10 @@ TopologicalSortFilterJoinNodes(std::vector<const Node*>& Out) {
}
// Find head of the toolchain corresponding to the given file.
const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
const std::string& InLanguage = getLanguage(In);
const Node* CompilationGraph::
FindToolChain(const sys::Path& In, const std::string* forceLanguage) const {
const std::string& InLanguage =
forceLanguage ? *forceLanguage : getLanguage(In);
const tools_vector_type& TV = getToolsVector(InLanguage);
if (TV.empty())
throw std::runtime_error("No toolchain corresponding to language"
@ -225,13 +234,55 @@ const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
// temporary variables.
int CompilationGraph::Build (const sys::Path& TempDir) {
// This is related to -x option handling.
cl::list<std::string>::const_iterator xIter = Languages.begin(),
xBegin = xIter, xEnd = Languages.end();
bool xEmpty = true;
const std::string* xLanguage = 0;
unsigned xPos = 0, xPosNext = 0, filePos = 0;
if (xIter != xEnd) {
xEmpty = false;
xPos = Languages.getPosition(xIter - xBegin);
cl::list<std::string>::const_iterator xNext = llvm::next(xIter);
xPosNext = (xNext == xEnd) ? std::numeric_limits<unsigned>::max()
: Languages.getPosition(xNext - xBegin);
xLanguage = (*xIter == "none") ? 0 : &(*xIter);
}
// For each input file:
for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
E = InputFilenames.end(); B != E; ++B) {
CB = B, E = InputFilenames.end(); B != E; ++B) {
sys::Path In = sys::Path(*B);
// Code for handling the -x option.
// Output: std::string* xLanguage (can be NULL).
if (!xEmpty) {
filePos = InputFilenames.getPosition(B - CB);
if (xPos < filePos) {
if (filePos < xPosNext) {
xLanguage = (*xIter == "none") ? 0 : &(*xIter);
}
else { // filePos >= xPosNext
// Skip xIters while filePos > xPosNext
while (filePos > xPosNext) {
++xIter;
xPos = xPosNext;
cl::list<std::string>::const_iterator xNext = llvm::next(xIter);
if (xNext == xEnd)
xPosNext = std::numeric_limits<unsigned>::max();
else
xPosNext = Languages.getPosition(xNext - xBegin);
xLanguage = (*xIter == "none") ? 0 : &(*xIter);
}
}
}
}
// Find the toolchain corresponding to this file.
const Node* N = FindToolChain(In);
const Node* N = FindToolChain(In, xLanguage);
// Pass file through the chain starting at head.
PassThroughGraph(In, N, TempDir);
}

View File

@ -165,7 +165,8 @@ namespace llvmc {
const llvm::sys::Path& TempDir) const;
// Find head of the toolchain corresponding to the given file.
const Node* FindToolChain(const llvm::sys::Path& In) const;
const Node* FindToolChain(const llvm::sys::Path& In,
const std::string* forceLanguage) const;
// Sort the nodes in topological order.
void TopologicalSort(std::vector<const Node*>& Out);

View File

@ -56,7 +56,7 @@ def llc : Tool<
[(in_language "llvm-bitcode"),
(out_language "assembler"),
(output_suffix "s"),
(cmd_line "llc $INFILE -o $OUTFILE")
(cmd_line "llc -f $INFILE -o $OUTFILE")
]>;
def llvm_gcc_assembler : Tool<
@ -68,6 +68,7 @@ def llvm_gcc_assembler : Tool<
(prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
]>;
// Default linker
def llvm_gcc_linker : Tool<
[(in_language "object-code"),
(out_language "executable"),
@ -79,6 +80,21 @@ def llvm_gcc_linker : Tool<
(prefix_list_option "Wl", (unpack_values), (help "pass options to linker"))
]>;
// Alternative linker for C++
// TOTHINK: how to implement this best?
// Something like input_file_language can only choose between two languages.
// def llvm_gcc_cpp_linker : Tool<
// [(in_language "object-code"),
// (out_language "executable"),
// (output_suffix "out"),
// (cmd_line "llvm-g++ $INFILE -o $OUTFILE"),
// (join),
// //(input_file_language "c++"),
// (prefix_list_option "L", (forward)),
// (prefix_list_option "l", (forward)),
// (prefix_list_option "Wl", (unpack_values))
// ]>;
// Language map
def LanguageMap : LanguageMap<

View File

@ -35,6 +35,9 @@ 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::list<std::string> Languages("x",
cl::desc("Specify the language of the following input files"),
cl::ZeroOrMore);
cl::opt<bool> VerboseMode("v",
cl::desc("Enable verbose mode"));
cl::opt<bool> WriteGraph("write-graph",