mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Use (actions) instead of option properties, support external options.
Also includes a major refactoring. See documentation for more information. llvm-svn: 60656
This commit is contained in:
parent
16ea827dfd
commit
f01331152a
@ -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_; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
74
tools/llvmc/driver/Tool.cpp
Normal file
74
tools/llvmc/driver/Tool.cpp
Normal 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
Loading…
Reference in New Issue
Block a user