Use (actions) instead of option properties, support external options.

Also includes a major refactoring. See documentation for more
information.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60656 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2008-12-07 16:41:11 +00:00
parent 6290f5cac2
commit f915253dfc
7 changed files with 1116 additions and 1143 deletions

View File

@ -27,14 +27,22 @@ namespace llvmc {
std::string Command_;
/// Args_ - Command arguments. Stdout redirection ("> file") is allowed.
std::vector<std::string> Args_;
/// StopCompilation_ - Should we stop compilation after executing
/// this action?
bool StopCompilation_;
/// OutFile_ - The output file name.
std::string OutFile_;
public:
Action() {}
Action (const std::string& C, const StrVector& A)
: Command_(C), Args_(A)
Action (const std::string& C, const StrVector& A,
bool S, const std::string& O)
: Command_(C), Args_(A), StopCompilation_(S), OutFile_(O)
{}
/// Execute - Executes the represented action.
int Execute() const;
int Execute () const;
bool StopCompilation () const { return StopCompilation_; }
const std::string& OutFile() { return OutFile_; }
};
}

View File

@ -15,7 +15,7 @@ class Tool<list<dag> l> {
list<dag> properties = l;
}
// Possible Tool properties
// Possible Tool properties.
def in_language;
def out_language;
@ -23,8 +23,9 @@ def output_suffix;
def cmd_line;
def join;
def sink;
def actions;
// Possible option types
// Possible option types.
def alias_option;
def switch_option;
@ -33,17 +34,16 @@ def parameter_list_option;
def prefix_option;
def prefix_list_option;
// Possible option properties
def extern_switch;
def extern_parameter;
def extern_list;
// Possible option properties.
def append_cmd;
def forward;
def forward_as;
def help;
def hidden;
def really_hidden;
def required;
def stop_compilation;
def unpack_values;
// Empty DAG marker.
def empty;
@ -51,6 +51,10 @@ def empty;
// The 'case' construct.
def case;
// Boolean operators.
def and;
def or;
// Primitive tests.
def switch_on;
def parameter_equals;
@ -59,9 +63,13 @@ def input_languages_contain;
def not_empty;
def default;
// Boolean operators.
def and;
def or;
// Possible actions.
def append_cmd;
def forward;
def forward_as;
def stop_compilation;
def unpack_values;
// Increase/decrease the edge weight.
def inc_weight;

View File

@ -36,22 +36,29 @@ namespace llvmc {
virtual ~Tool() {}
virtual Action GenerateAction (const PathVector& inFiles,
const llvm::sys::Path& outFile,
bool HasChildren,
const llvm::sys::Path& TempDir,
const InputLanguagesSet& InLangs,
const LanguageMap& LangMap) const = 0;
virtual Action GenerateAction (const llvm::sys::Path& inFile,
const llvm::sys::Path& outFile,
bool HasChildren,
const llvm::sys::Path& TempDir,
const InputLanguagesSet& InLangs,
const LanguageMap& LangMap) const = 0;
virtual const char* Name() const = 0;
virtual const char** InputLanguages() const = 0;
virtual const char* OutputLanguage() const = 0;
virtual const char* OutputSuffix() const = 0;
virtual bool IsLast() const = 0;
virtual bool IsJoin() const = 0;
protected:
/// OutFileName - Generate the output file name.
llvm::sys::Path OutFilename(const llvm::sys::Path& In,
const llvm::sys::Path& TempDir,
bool StopCompilation,
const char* OutputSuffix) const;
};
/// JoinTool - A Tool that has an associated input file list.
@ -61,10 +68,11 @@ namespace llvmc {
void ClearJoinList() { JoinList_.clear(); }
bool JoinListEmpty() const { return JoinList_.empty(); }
Action GenerateAction(const llvm::sys::Path& outFile,
Action GenerateAction(bool HasChildren,
const llvm::sys::Path& TempDir,
const InputLanguagesSet& InLangs,
const LanguageMap& LangMap) const {
return GenerateAction(JoinList_, outFile, InLangs, LangMap);
return GenerateAction(JoinList_, HasChildren, TempDir, InLangs, LangMap);
}
// We shouldn't shadow base class's version of GenerateAction.
using Tool::GenerateAction;

View File

@ -11,6 +11,35 @@
//
//===----------------------------------------------------------------------===//
def OptList : OptionList<[
(switch_option "emit-llvm",
(help "Emit LLVM bitcode files instead of native object files")),
(switch_option "E",
(help "Stop after the preprocessing stage, do not run the compiler")),
(switch_option "fsyntax-only",
(help "Stop after checking the input for syntax errors")),
(switch_option "opt",
(help "Enable opt")),
(switch_option "S",
(help "Stop after compilation, do not assemble")),
(switch_option "c",
(help "Compile and assemble, but do not link")),
(parameter_option "linker",
(help "Choose linker (possible values: gcc, g++)")),
(parameter_list_option "include",
(help "Include the named file prior to preprocessing")),
(prefix_list_option "I",
(help "Add a directory to include path")),
(prefix_list_option "Wa,",
(help "Pass options to assembler")),
(prefix_list_option "L",
(help "Add a directory to link path")),
(prefix_list_option "l",
(help "Search a library when linking")),
(prefix_list_option "Wl,",
(help "Pass options to linker"))
]>;
class llvm_gcc_based <string cmd_prefix, string in_lang> : Tool<
[(in_language in_lang),
(out_language "llvm-bitcode"),
@ -25,16 +54,13 @@ class llvm_gcc_based <string cmd_prefix, string in_lang> : Tool<
!strconcat(cmd_prefix, " -fsyntax-only $INFILE"),
(default),
!strconcat(cmd_prefix, " -c $INFILE -o $OUTFILE -emit-llvm"))),
(switch_option "emit-llvm", (stop_compilation),
(help "Emit LLVM intermediate files instead of native object files")),
(switch_option "E", (stop_compilation),
(help "Stop after the preprocessing stage, do not run the compiler")),
(switch_option "fsyntax-only", (stop_compilation),
(help "Stop after checking the input for syntax errors")),
(parameter_list_option "include", (forward),
(help "Include the named file prior to preprocessing")),
(prefix_list_option "I", (forward),
(help "Add a directory to include path")),
(actions
(case
(switch_on "emit-llvm"), (stop_compilation),
(switch_on "E"), (stop_compilation),
(switch_on "fsyntax-only"), (stop_compilation),
(not_empty "include"), (forward "include"),
(not_empty "I"), (forward "include"))),
(sink)
]>;
@ -46,7 +72,6 @@ def llvm_gcc_mxx : llvm_gcc_based<"llvm-gcc -x objective-c++", "objective-c++">;
def opt : Tool<
[(in_language "llvm-bitcode"),
(out_language "llvm-bitcode"),
(switch_option "opt", (help "Enable opt")),
(output_suffix "bc"),
(cmd_line "opt -f $INFILE -o $OUTFILE")
]>;
@ -62,8 +87,8 @@ def llc : Tool<
[(in_language "llvm-bitcode"),
(out_language "assembler"),
(output_suffix "s"),
(switch_option "S", (stop_compilation),
(help "Stop after compilation, do not assemble")),
(actions (case
(switch_on "S"), (stop_compilation))),
(cmd_line "llc -f $INFILE -o $OUTFILE")
]>;
@ -72,36 +97,28 @@ def llvm_gcc_assembler : Tool<
(out_language "object-code"),
(output_suffix "o"),
(cmd_line "llvm-gcc -c -x assembler $INFILE -o $OUTFILE"),
(switch_option "c", (stop_compilation),
(help "Compile and assemble, but do not link")),
(prefix_list_option "Wa,", (unpack_values), (help "Pass options to assembler"))
(actions (case
(switch_on "c"), (stop_compilation),
(not_empty "Wa,"), (unpack_values "Wa,")))
]>;
// Base class for linkers
class llvm_gcc_based_linker <string cmd_prefix> : Tool<
[(in_language "object-code"),
(out_language "executable"),
(output_suffix "out"),
(cmd_line !strconcat(cmd_prefix, " $INFILE -o $OUTFILE")),
(join),
(actions (case
(not_empty "L"), (forward "L"),
(not_empty "l"), (forward "l"),
(not_empty "Wl,"), (unpack_values "Wl,")))
]>;
// Default linker
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"))
]>;
def llvm_gcc_linker : llvm_gcc_based_linker<"llvm-gcc">;
// Alternative linker for C++
def llvm_gcc_cpp_linker : Tool<
[(in_language "object-code"),
(out_language "executable"),
(output_suffix "out"),
(cmd_line "llvm-g++ $INFILE -o $OUTFILE"),
(join),
(parameter_option "linker",
(help "Choose linker (possible values: gcc, g++)")),
(prefix_list_option "L", (forward)),
(prefix_list_option "l", (forward)),
(prefix_list_option "Wl,", (unpack_values))
]>;
def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"llvm-g++">;
// Language map

View File

@ -29,7 +29,6 @@ using namespace llvm;
using namespace llvmc;
extern cl::list<std::string> InputFilenames;
extern cl::opt<std::string> OutputFilename;
extern cl::list<std::string> Languages;
namespace llvmc {
@ -143,30 +142,6 @@ void CompilationGraph::insertEdge(const std::string& A, Edge* Edg) {
B.IncrInEdges();
}
namespace {
sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
const std::string& Suffix) {
sys::Path Out;
// Make sure we don't end up with path names like '/file.o' if the
// TempDir is empty.
if (TempDir.empty()) {
Out.set(BaseName);
}
else {
Out = TempDir;
Out.appendComponent(BaseName);
}
Out.appendSuffix(Suffix);
// NOTE: makeUnique always *creates* a unique temporary file,
// which is good, since there will be no races. However, some
// tools do not like it when the output file already exists, so
// they have to be placated with -f or something like that.
Out.makeUnique(true, NULL);
return Out;
}
}
// Pass input file through the chain until we bump into a Join node or
// a node that says that it is the last.
void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
@ -174,12 +149,10 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
const InputLanguagesSet& InLangs,
const sys::Path& TempDir,
const LanguageMap& LangMap) const {
bool Last = false;
sys::Path In = InFile;
const Node* CurNode = StartNode;
while(!Last) {
sys::Path Out;
while(true) {
Tool* CurTool = CurNode->ToolPtr.getPtr();
if (CurTool->IsJoin()) {
@ -188,32 +161,19 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
break;
}
// Since toolchains do not have to end with a Join node, we should
// check if this Node is the last.
if (!CurNode->HasChildren() || CurTool->IsLast()) {
if (!OutputFilename.empty()) {
Out.set(OutputFilename);
}
else {
Out.set(In.getBasename());
Out.appendSuffix(CurTool->OutputSuffix());
}
Last = true;
}
else {
Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix());
}
Action CurAction = CurTool->GenerateAction(In, CurNode->HasChildren(),
TempDir, InLangs, LangMap);
if (int ret = CurTool->GenerateAction(In, Out, InLangs, LangMap).Execute())
if (int ret = CurAction.Execute())
throw error_code(ret);
if (Last)
if (CurAction.StopCompilation())
return;
CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
InLangs,
CurNode->Name())->ToolName());
In = Out; Out.clear();
In = CurAction.OutFile();
}
}
@ -351,36 +311,24 @@ int CompilationGraph::Build (const sys::Path& TempDir,
sys::Path Out;
const Node* CurNode = *B;
JoinTool* JT = &dynamic_cast<JoinTool&>(*CurNode->ToolPtr.getPtr());
bool IsLast = false;
// Are there any files in the join list?
if (JT->JoinListEmpty())
continue;
// Is this the last tool in the toolchain?
// NOTE: we can process several toolchains in parallel.
if (!CurNode->HasChildren() || JT->IsLast()) {
if (OutputFilename.empty()) {
Out.set("a");
Out.appendSuffix(JT->OutputSuffix());
}
else
Out.set(OutputFilename);
IsLast = true;
}
else {
Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix());
}
Action CurAction = JT->GenerateAction(CurNode->HasChildren(),
TempDir, InLangs, LangMap);
if (int ret = JT->GenerateAction(Out, InLangs, LangMap).Execute())
if (int ret = CurAction.Execute())
throw error_code(ret);
if (!IsLast) {
const Node* NextNode =
&getNode(ChooseEdge(CurNode->OutEdges, InLangs,
CurNode->Name())->ToolName());
if (CurAction.StopCompilation())
return 0;
const Node* NextNode =
&getNode(ChooseEdge(CurNode->OutEdges, InLangs,
CurNode->Name())->ToolName());
PassThroughGraph(Out, NextNode, InLangs, TempDir, LangMap);
}
}
return 0;

View File

@ -0,0 +1,74 @@
//===--- Tool.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.
//
//===----------------------------------------------------------------------===//
//
// Tool base class - implementation details.
//
//===----------------------------------------------------------------------===//
#include "llvm/CompilerDriver/Tool.h"
#include "llvm/System/Path.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
using namespace llvmc;
extern cl::opt<std::string> OutputFilename;
namespace {
sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
const std::string& Suffix) {
sys::Path Out;
// Make sure we don't end up with path names like '/file.o' if the
// TempDir is empty.
if (TempDir.empty()) {
Out.set(BaseName);
}
else {
Out = TempDir;
Out.appendComponent(BaseName);
}
Out.appendSuffix(Suffix);
// NOTE: makeUnique always *creates* a unique temporary file,
// which is good, since there will be no races. However, some
// tools do not like it when the output file already exists, so
// they have to be placated with -f or something like that.
Out.makeUnique(true, NULL);
return Out;
}
}
sys::Path Tool::OutFilename(const sys::Path& In,
const sys::Path& TempDir,
bool StopCompilation,
const char* OutputSuffix) const {
sys::Path Out;
if (StopCompilation) {
if (!OutputFilename.empty()) {
Out.set(OutputFilename);
}
else if (IsJoin()) {
Out.set("a");
Out.appendSuffix(OutputSuffix);
}
else {
Out.set(In.getBasename());
Out.appendSuffix(OutputSuffix);
}
}
else {
if (IsJoin())
Out = MakeTempFile(TempDir, "tmp", OutputSuffix);
else
Out = MakeTempFile(TempDir, In.getBasename(), OutputSuffix);
}
return Out;
}

File diff suppressed because it is too large Load Diff